import { CellType } from ".";
import { classNameDeal, dom, mixins, getNodeInfo, dealNodeClass } from "../tool";

interface PropType {
    x?: number | null;
    y?: number | null;
    child?: CellType;
    target?: HTMLElement;
    style?: any;
}

export interface BoxType extends CellType {
    new(prop?: PropType): BoxType;
    render: (node?: HTMLElement) => HTMLElement;
    setChild: (child: CellType) => void;
    getPosition: () => { x: number, y: number } | null;
    mouseDown: (x: number, y:number) => any;
    mouseMove: (x:number,y:number,handle: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8)=>any;
    mouseUp: ()=>any;
    getNodeInfo: ()=> {
        x: number;
        left: number;
        right: number;
        y: number;
        top: number;
        bottom: number;
        width: number;
        height: number;
    }
    style: any;
}

function Box(this: BoxType, prop?: PropType) {
    const { x, y, child, target, style } = prop || {};
    console.log(x,y)
    let pNode: any;
    let hasMoved: boolean = false;
    let hasDown: boolean = false;
    let childInstance = child;
    let childNode:any;
    let nodeInfo:any;
    const container: HTMLElement = dom('div', { className: 'gkh-doc-box', target });
    const content: any = dom('div', { className: 'gkh-box-content', target: container });
    let left: number = 0;
    let top: number = 0;
    let preX: number = 0;
    let preY: number = 0;
    let parentNodeInfo:any = {};
    let width: number = 0;
    let height: number = 0;
    this.getAttrData = () => {
        const attrData = child?.getAttrData();
        if (hasMoved) {
            attrData.x = content.offsetLeft - container.offsetLeft;
            attrData.y = content.offsetTop - container.offsetTop;
        }
        console.log(content.offsetLeft,content.offsetTop)
        return attrData;
    }
    
    const setStyle = (style:any)=>{
        for (var key in style) {
            if(key=='width' || key=='minHeight' || key=='height'){
                if(hasMoved){
                    content.style[key] = style[key];
                }else{
                    container.style[key] = style[key];
                }
            }else{
                childNode.style[key] = style[key];
            }
        }
        return true;
    }
    this.setChild = (arg: CellType): void => {
        mixins(this, arg);
        childInstance = child;
        content.innerHTML = "";
        childNode = arg.render();
        if(style){
            setStyle(style);
        }
        content.appendChild(childNode);
    }

    this.getPosition = () => {
        if (hasMoved) {
            return {
                x: content.offsetLeft - container.offsetLeft,
                y: content.offsetTop - container.offsetTop,
            }
        }
        return null;
    }

    this.render = (target) => {
        if (target) {
            target.appendChild(container);
            pNode = target;
        }
        return container;
    }

    if (target) {
        pNode = target;
    }
    if (x || y) {
        dealNodeClass(container,'gkh-box-moved',true);
        if (x) {
            content.style.left = String(x).concat("px");
        }
        if (y) {
            content.style.top = String(y).concat("px");
        }
        hasMoved = true;
    }
    this.mouseDown = (x,y)=>{
        hasDown = true;
        left = content.offsetLeft;
        top = content.offsetTop;
        width = content.offsetWidth;
        height = content.offsetHeight;
        preX = x;
        preY = y;
        if(!pNode){
            pNode = container.parentElement;
        }
        parentNodeInfo = getNodeInfo(pNode);
    }
    this.mouseMove = (clientX,clientY,handle)=>{
        if (hasDown) {
            switch (handle) {
                case 1: {
                    const dw = width + clientX - preX;
                    if (dw > 0 && dw < parentNodeInfo.width) {
                        if(hasMoved){
                            content.style.width = dw.toString().concat('px');
                        }else{
                            container.style.width = dw.toString().concat('px');
                        }
                        childNode.style.width = dw.toString().concat('px');
                    }
                } break;
                case 2: {
                    const dh = height + clientY - preY;
                    if (dh > 0 && dh < parentNodeInfo.height) {
                        if(hasMoved){
                            content.style.minHeight = dh.toString().concat('px');
                        }else{
                            container.style.minHeight = dh.toString().concat('px');
                        }
                        childNode.style.minHeight = dh.toString().concat('px');
                    }
                } break;
                case 3: {
                    const dx = clientX - parentNodeInfo.x + clientX - preX;
                    const dw = width + preX - clientX;
                    if (dw > 0 && dw < parentNodeInfo.width) {
                        if(hasMoved){
                            content.style.left = dx.toString().concat('px');
                            content.style.width = dw.toString().concat('px');
                        }else{
                            container.style.left = dx.toString().concat('px');
                            container.style.width = dw.toString().concat('px');
                        }
                        childNode.style.left = dx.toString().concat('px');
                        childNode.style.width = dw.toString().concat('px');
                    }
                } break;
                case 4: {
                    const dy = clientY - parentNodeInfo.y + clientY - preY;
                    const dh = height + preY - clientY;
                    if (dh > 0 && dh < parentNodeInfo.height) {
                        if(hasMoved){
                            content.style.top = dy.toString().concat('px');
                            content.style.minHeight = dh.toString().concat('px');
                        }else{
                            container.style.top = dy.toString().concat('px');
                            container.style.minHeight = dh.toString().concat('px');
                        }
                        childNode.style.top = dy.toString().concat('px');
                        childNode.style.minHeight = dh.toString().concat('px');
                    }
                } break;
            }
            if(handle>4){
                if(!hasMoved){
                    hasMoved = true;
                    content.style.width = String(container.offsetWidth).concat('px');
                    content.style.minHeight = String(container.offsetHeight).concat('px');
                    dealNodeClass(container,'gkh-box-moved',true);
                }
                content.style.left = String(left+clientX-preX).concat("px");
                content.style.top = String(top+clientY-preY).concat("px");
            }
        }
    }
    this.mouseUp = ()=>{
        hasDown = false;
    }
    this.getNodeInfo = ()=>{
        nodeInfo = getNodeInfo(content);
        return nodeInfo;
    };
    Object.defineProperty(this,"style",{
        get(){
            return window.getComputedStyle(childNode);
        },
        set: setStyle
    });
    
    if (child) {
        this.setChild(child);
    }
    return this;
}

export default Box as unknown as BoxType;